package com.htx.zqs.blesmartmask.utils;

import android.annotation.SuppressLint;
import android.util.Log;

import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleReadCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.htx.zqs.blesmartmask.bean.Courses;
import com.htx.zqs.blesmartmask.listeners.BleNotifyListener;

import java.util.Random;
import java.util.concurrent.TimeUnit;

import io.reactivex.Flowable;
import io.reactivex.functions.Consumer;

/**
 * Created by KomoriWu
 * on 2019/2/18.
 */
public class BleUtils {
    public static final String TAG = BleUtils.class.getSimpleName();
    public static final String BLE_NAME = "Metis Genie Mask";
    public static final String UUID_SERVICE = "0000fff0-0000-1000-8000-00805f9b34fb";
    public static final String UUID_CHARACTERISTIC_NOTIFY = "0000fff1-0000-1000-8000-00805f9b34fb";
    public static final String UUID_CHARACTERISTIC_WRITE = "0000fff2-0000-1000-8000-00805f9b34fb";

    public static void write(final BleDevice bleDevice, final byte[] data, BleWriteCallback callback) {
        Logger.d(TAG, "write to mac:" + bleDevice.getMac() + "---data:" +
                Utils.bytesToHexString(data));
        if (callback == null) {
            callback = new BleWriteCallback() {
                @Override
                public void onWriteSuccess(int current, int total, byte[] justWrite) {
//                    Logger.d(TAG, "onWriteSuccess:" + bleDevice.getMac() + "---data:" +
//                            Utils.bytesToHexString(justWrite));
                }

                @Override
                public void onWriteFailure(BleException exception) {

                }
            };
        }
        BleManager.getInstance().write(bleDevice, BleUtils.UUID_SERVICE,
                BleUtils.UUID_CHARACTERISTIC_WRITE, data, callback);
    }

    public static void read(final BleDevice bleDevice, final byte[] data, BleReadCallback callback) {
        Logger.d(TAG, "read to mac:" + bleDevice.getMac() + "---data:" +
                Utils.bytesToHexString(data));
        if (callback == null) {
            callback = new BleReadCallback() {

                @Override
                public void onReadSuccess(byte[] data) {

                }

                @Override
                public void onReadFailure(BleException exception) {

                }
            };
        }
        BleManager.getInstance().read(bleDevice, BleUtils.UUID_SERVICE,
                BleUtils.UUID_CHARACTERISTIC_WRITE, callback);
    }

    public static void notify(final BleDevice bleDevice, final BleNotifyListener notifyListener) {
        BleManager.getInstance().notify(bleDevice, BleUtils.UUID_SERVICE,
                BleUtils.UUID_CHARACTERISTIC_NOTIFY, new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        Logger.d(TAG, "onNotifySuccess" + bleDevice.getMac());
                    }

                    @SuppressLint("CheckResult")
                    @Override
                    public void onNotifyFailure(BleException exception) {
                        Logger.d(TAG, "onNotifyFailure" + bleDevice.getMac());
                        Flowable.just("").delay(1, TimeUnit.SECONDS)
                                .subscribe(new Consumer<String>() {
                                    @Override
                                    public void accept(String s) {
                                        BleUtils.notify(bleDevice, notifyListener);
                                    }
                                });
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {
                        //data为十进制的byte
                        Logger.d(TAG, "notify by mac:" + bleDevice.getMac() + "---data:" +
                                Utils.bytesToHexString(data));
                        if (notifyListener != null) {
                            notifyListener.onSuccess(data);
                        }
                    }
                });
    }

    public static void stopNotify(BleDevice bleDevice) {
        BleManager.getInstance().stopNotify(bleDevice, BleUtils.UUID_SERVICE,
                BleUtils.UUID_CHARACTERISTIC_NOTIFY);
    }

    //command 0x开头为16精制
    //油水测试
    public static byte[] getTestWaterCommand(int time) {
        byte[] buff = new byte[10];
        int[] intArray = {0x41, 0x54, 0x2d, 0x50, 0xc2, 0x83, 0x83, time, 0x0d, 0x0a};
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        return buff;
    }

    //开始面膜
    public static byte[] getWaterStartCommand(Courses course, int level, int countTime) {
        if (course != null) {
            int[] intArray = {0x41, 0x54, 0x2d, 0x51,
                    194, 131, 131, 0x00,
                    0x00, 0x00, 0x00, 0x00,
                    0x00,
                    0x00, 0x00, 0x00};

            int frequency = course.getFrequency();
            int percentage = course.getPercentage();
            if (frequency < 40) {
                frequency = 40;
            }
            if (frequency > 16000) {
                frequency = 16000;
            }
            if (frequency < 500) {
                int i = (int) (10000 / (frequency * 1.536));
                if (i > 255) {
                    i = 255;
                }
                intArray[4] = i;

                i = (int) (i * (percentage / 100.0));
                intArray[5] = i;
                intArray[6] = 0xee;

            } else {
                int x = 0;
                if (frequency < 1000) {
                    x = 5;
                } else if (frequency <= 2000) {
                    x = 4;
                } else if (frequency <= 4000) {
                    x = 3;
                } else if (frequency <= 8000) {
                    x = 2;
                } else {
                    x = 1;
                }

                int L = (int) (256 - 8000000 / (frequency * Math.pow(2, x + 1)));
                if (L < 1) {
                    L = 1;
                }
                if (L > 0xfe) {
                    L = 0xfe;
                }

                if (percentage < 5) {
                    percentage = 5;
                }
                if (percentage > 95) {
                    percentage = 95;
                }
                percentage = 100 - percentage;
                int H = (int) (256 - percentage * (256 - L) / 100.0);
                intArray[4] = H;
                intArray[5] = L;
                intArray[6] = x + 0x80;
            }

            int time0 = course.getTimeone();
            int time1 = course.getTimetwo();
            int time2 = course.getTimethree();

            if (time0 + time1 + time2 < countTime) {
                intArray[8] = time0;
                intArray[7] = countTime - time0;
                intArray[12] = countTime - time0 - time1;
            } else {
                intArray[8] = time0;
                intArray[7] = time1 + time2;
                intArray[12] = time2;
            }

            int index = course.getId();
            intArray[9] = (int) (index / 256.0 / 256.0);
            intArray[10] = (int) (index % (256 * 256) / 256.0);
            intArray[11] = index % 256;

            int p = 100 - (level * 50);
//            if (level == 0) {
//                p = 97;
//            } else if (level == 1) {
//                p = 64;
//            } else if (level == 2) {
//                p = 0;
//            }

            p = 100 - level;


            p = (int) (256 - (256 - 131) * p / 100.0);
            if (p > 255) {
                p = 255;
            }
            if (p < 0) {
                p = 0;
            }

            intArray[13] = p;
            intArray[14] = p;
            intArray[15] = p;
            Log.e("384", "waterStart: " + intArray);
            Log.e("==========blue==385====" + course.getName(), "===============" + p);

            byte[] buff = new byte[intArray.length];
            for (int i = 0; i < intArray.length; i++) {
                buff[i] = (byte) (intArray[i] & 0xff);
            }
            return buff;
        }
        return new byte[]{0};
    }

    //暂停课程
    public static byte[] getPauseCourseCommand() {
        int[] intArray = {0x41, 0x54, 0x2d, 0x52, 0xff, 0x0d, 0x0a};
        byte[] buff = new byte[intArray.length];
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        return buff;
    }

    //继续课程
    public static byte[] getContinueCourseCommand() {
        int[] intArray = {0x41, 0x54, 0x2d, 0x52, 0x01, 0x0d, 0x0a};
        byte[] buff = new byte[intArray.length];
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        return buff;
    }

    //停止课程
    public static byte[] getStopCourseCommand() {
        int[] intArray = {0x41, 0x54, 0x2d, 0x52, 0x00, 0x0d, 0x0a};
        byte[] buff = new byte[intArray.length];
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        return buff;
    }

    //设置电压 0-100 实际为131-255
    public static byte[] getChangVoltageCommand(int level) {
        int[] intArray = {0x41, 0x54, 0x2d, 0x56, 0x01, 0x0d, 0x0a};
        int p;
        p = 125 - level;
        p = 256 - (256 - 131) * p / 125;
        if (p > 255) {
            p = 255;
        }
        if (p < 0) {
            p = 0;
        }
        intArray[4] = p;
        byte[] buff = new byte[intArray.length];
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        return buff;
    }

    // 多连接时设备序号设定 Command[4]: 设定排列序号:01标示第一个设备 目前只标记第一个
    public static byte[] getSerialNumCommand() {
        int[] intArray = {0x41, 0x54, 0x2d, 0x58, 0x01, 0x0d, 0x0a};
        byte[] buff = new byte[intArray.length];
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        return buff;
    }

    //获取课程执行累计时间
    public static byte[] getUseTimesCommand() {
        byte[] buff = new byte[10];
        int[] intArray = {0x41, 0x54, 0x2d, 0x4d, 0x0d, 0x0a};
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        return buff;
    }

    //默认的加密指令
    public static byte[] getDefaultKeyCommand() {
        byte[] buff = new byte[9];
        int[] intArray = {0x41, 0x54, 0x2d, 0x59, 0x34, 0x12, 0x15, 0xa0, 0x08};
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        return buff;
    }

    //加密解密 自己随机
    public static byte[] getKeyCommand() {
        Random r = new Random();
        int n1 = r.nextInt(255) + 1;
        int n2 = r.nextInt(255) + 1;
        int n3 = r.nextInt(255) + 1;
        int n4 = r.nextInt(255) + 1;
        int n5 = r.nextInt(255) + 1;
        byte[] buff = new byte[9];
        int[] intArray = {0x41, 0x54, 0x2d, 0x59};
        String[] stringArray = {Integer.toHexString(n1), Integer.toHexString(n2),
                Integer.toHexString(n3), Integer.toHexString(n4), Integer.toHexString(n5)};
        for (int i = 0; i < intArray.length; i++) {
            buff[i] = (byte) (intArray[i] & 0xff);
        }
        for (int i = 4; i < 9; i++) {
            buff[i] = (byte) (hexStringToBytes(stringArray[i - 4])[0] & 0xff);
        }
        return buff;
    }

    public static byte[] hexStringToBytes(String hexString) {
        if (hexString == null || hexString.equals("")) {
            return null;
        }
        if (hexString.length() < 2) {
            hexString = "0" + hexString;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }

    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }


}
